package com.jf.core;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.jf.config.Constants;
import com.jf.config.JbsfConfig;
import com.jf.handler.Handler;
import com.jf.log.Log;
import com.wbcs.config.ConfigLoadManager;
import com.wbcs.config.xml.XmlAssistant;
import com.wbcs.util.Tools;
import com.wbcs.util.WbcsClassLoader;

/**
 * 
 * @author liqin
 *
 */
public class JbsfFilter implements Filter {
	
	private Handler handler;
	private String encoding;
	private JbsfConfig jbsfConfig;
	private Constants constants;
	private static final Jbsf jbsf = Jbsf.me();
	public static FilterConfig filterConfig;
	private static Log log;
	private int contextPathLength;
	
	public void init(FilterConfig filterConfig) throws ServletException {
		JbsfFilter.filterConfig = filterConfig;
		createjfConfig(filterConfig.getInitParameter("configClass"), filterConfig.getInitParameter("configpath"));
		
		if (jbsf.init(jbsfConfig, filterConfig.getServletContext()) == false) {
			throw new RuntimeException("jf init error!");
		}
		
		handler = jbsf.getHandler();
		constants = Config.getConstants();
		encoding = constants.getEncoding();
		jbsfConfig.afterjfStart();
		
		String contextPath = filterConfig.getServletContext().getContextPath();
		contextPathLength = (contextPath == null || "/".equals(contextPath) ? 0 : contextPath.length());
	}
	
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest)req;
		HttpServletResponse response = (HttpServletResponse)res;
		request.setCharacterEncoding(encoding);
		
		String target = request.getRequestURI();
		if (contextPathLength != 0) {
			target = target.substring(contextPathLength);
		}
		
		boolean[] isHandled = {false};
		try {
			handler.handle(target, request, response, isHandled);
		}
		catch (Exception e) {
			if (log.isErrorEnabled()) {
				String qs = request.getQueryString();
				log.error(qs == null ? target : target + "?" + qs, e);
			}
		}
		
		if (isHandled[0] == false) {
			chain.doFilter(request, response);
		}
	}
	
	public void destroy() {
		jbsfConfig.beforejfStop();
		jbsf.stopPlugins();
	}
	
	/**
	 * 创建启动配置文件
	 * @param configClass 默认Config对象
	 * @param configpath  用户配置Config对象
	 * @param homeAbsPath 服务器目录绝对路径
	 */
	private void createjfConfig(String configClass, String configpath) {
		
		if (configClass == null) {
			throw new RuntimeException("Please set configClass parameter of JbsfFilter in web.xml");
		}
		
		//读取wbcs.cfg.xml文件中system item name=configclass 标签，得到vaue中的配置路径，如果取不到，则执行默认配置
		if(configpath == null)
		{
			throw new RuntimeException("Please set configpath parameter of JbsfFilter in web.xml");
		}
		/*homeAbsPath = Tools.standardFilePath(homeAbsPath);
		configpath= homeAbsPath + Tools.getRealKeyByDefine("classpath",configpath).replace("/", "\\");
		String prjcfgpath = configpath + (configpath.endsWith("/") ? "wbcs.cfg.xml" :  "\\wbcs.cfg.xml");*/
		com.wbcs.config.Config.configpath = configpath;
		ConfigLoadManager.currentDynClassLoader=new WbcsClassLoader(Thread.currentThread().getContextClassLoader());//不影响WbcsPlugin重新创建，每次创建具有独立的pojo对象
		XmlAssistant xmlAssistant = XmlAssistant.getInstance();
		String prjConfigClass = xmlAssistant.getElementValueProp(xmlAssistant.loadXmlDocument("wbcs.cfg.xml"), "//*[local-name()='wbcs-config']/*[local-name()='system']/*[local-name()='item'][@name='configclass']", "@value");
		if(!Tools.isEmpty(prjConfigClass, true))
		{
			configClass = prjConfigClass;
		}
		
		Object temp = null;
		try {
			temp = Class.forName(configClass).newInstance();
		} catch (Exception e) {
			throw new RuntimeException("Can not create instance of class: " + configClass, e);
		}
		
		if (temp instanceof JbsfConfig) {
			jbsfConfig = (JbsfConfig)temp;
		} else {
			throw new RuntimeException("Can not create instance of class: " + configClass + ". Please check the config in web.xml");
		}
	}
	
	static void initLog() {
		log = Log.getLog(JbsfConfig.class);
	}
}
